
package com.idealighter.game.games.zjh.util;

import com.google.common.collect.HashMultiset;
import com.google.common.collect.Multiset;

import com.idealighter.game.games.common.CardSuit;
import com.idealighter.game.games.zjh.struct.ZjhCard;
import com.idealighter.game.games.zjh.struct.ZjhCardsType;

import java.util.List;
import java.util.Set;
import java.util.TreeSet;

/**
 * 炸金花牌型获取 .
 * 
 * @date 2016年6月27日 上午11:30:00
 *
 */
public class ZjhCardsTypeGetter {

  private ZjhCardsTypeGetter() {}

  /**
   * 获取牌型 . BAO_ZI(6), //豹子 SHUN_JIN(5), //顺金 JIN_HUA(4), //金花 SHUN_ZI(3), //顺子 DUI_ZI(2), //对子
   * DAN_ZHAN(1), //单张 ER_SAN_WU(0), //235
   * 
   * @param cards .
   * @return
   */
  public static ZjhCardsType geCardsType(List<ZjhCard> cards) {
    if (isBaoZi(cards)) {
      return ZjhCardsType.BAO_ZI;
    } else if (isShunJin(cards)) {
      return ZjhCardsType.SHUN_JIN;
    } else if (isJinHua(cards)) {
      return ZjhCardsType.JIN_HUA;
    } else if (isShunZi(cards)) {
      return ZjhCardsType.SHUN_ZI;
    } else if (isDuiZi(cards)) {
      return ZjhCardsType.DUI_ZI;
    } else if (isErSanWu(cards)) {
      return ZjhCardsType.ER_SAN_WU;
    } else if (isDanZhan(cards)) {
      return ZjhCardsType.DAN_ZHAN;
    }

    throw new RuntimeException("不能识别牌型的牌[" + cards + "]");
  }

  /**
   * 是不是豹子.
   * 
   * @param cards .
   * @return
   */
  private static boolean isBaoZi(List<ZjhCard> cards) {

    return cards.get(0).getNum() == cards.get(1).getNum()
        && cards.get(1).getNum() == cards.get(2).getNum();
  }

  /**
   * 是否顺金 .
   * 
   * @param cards .
   * @return
   */
  private static boolean isShunJin(List<ZjhCard> cards) {

    return isShunZi(cards) && isJinHua(cards);
  }

  /**
   * 是否顺子 .
   * 
   * @param cards .
   * @return
   */
  private static boolean isShunZi(List<ZjhCard> cards) {
    TreeSet<Integer> cardNums = new TreeSet<>();
    TreeSet<Integer> cardPowers = new TreeSet<>();
    for (ZjhCard card : cards) {
      cardNums.add(card.getNum());
      cardPowers.add(card.getPower());
    }

    Integer min = cardNums.first();
    Integer middle = cardNums.higher(min);
    Integer max = cardNums.last();

    Integer minPower = cardPowers.first();
    Integer middlePower = cardPowers.higher(minPower);
    Integer maxPower = cardPowers.last();

    // 要满足AKQ类型
    return (min + 1 == middle && middle + 1 == max)
        || (minPower + 1 == middlePower && middlePower + 1 == maxPower);
  }

  /**
   * 是否顺金 .
   * 
   * @param cards .
   * @return
   */
  private static boolean isJinHua(List<ZjhCard> cards) {

    return cards.get(0).type == cards.get(1).type && cards.get(1).type == cards.get(2).type;
  }

  /**
   * 是否对子 .
   * 
   * @param cards .
   * @return
   */
  private static boolean isDuiZi(List<ZjhCard> cards) {
    Multiset<Integer> cardNums = HashMultiset.create();
    for (ZjhCard card : cards) {
      cardNums.add(card.getNum());
    }

    return cardNums.elementSet().size() == 2;
  }


  /**
   * 是否单张 .
   * 
   * @param cards .
   * @return
   */
  private static boolean isDanZhan(List<ZjhCard> cards) {
    Multiset<Integer> cardNums = HashMultiset.create();
    for (ZjhCard card : cards) {
      cardNums.add(card.getNum());
    }

    return cardNums.elementSet().size() == 3;
  }

  /**
   * 是否二三五，不同花色 .
   * 
   * @param cards .
   * @return
   */
  private static boolean isErSanWu(List<ZjhCard> cards) {
    Multiset<Integer> cardNums = HashMultiset.create();
    Multiset<CardSuit> cardSuits = HashMultiset.create();
    for (ZjhCard card : cards) {
      cardNums.add(card.getNum());
      cardSuits.add(card.type);
    }

    Set<Integer> elements = cardNums.elementSet();
    return elements.contains(2) && elements.contains(3) && elements.contains(5)
        && cardSuits.elementSet().size() == 3;
  }

}
